package cn.iocoder.yudao.module.call.controller.admin.record;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.call.api.record.dto.CallRecordIvrDTO;
import cn.iocoder.yudao.module.call.controller.admin.record.vo.*;
import cn.iocoder.yudao.module.call.dal.dataobject.ivrintentionlabelstatistics.IvrIntentionLabelStatisticsDO;
import cn.iocoder.yudao.module.call.dal.dataobject.record.CallRecordDO;
import cn.iocoder.yudao.module.call.dal.dataobject.record.CallRecordTranslateDO;
import cn.iocoder.yudao.module.call.dal.dataobject.task.CallTaskDO;
import cn.iocoder.yudao.module.call.enums.CallTypeEnum;
import cn.iocoder.yudao.module.call.enums.IvrKeywordsBranchTypeEnum;
import cn.iocoder.yudao.module.call.mq.producer.intention.IntentionProducer;
import cn.iocoder.yudao.module.call.mq.producer.translate.CallTranslateProducer;
import cn.iocoder.yudao.module.call.service.ivrintentionlabelstatistics.IvrIntentionLabelStatisticsService;
import cn.iocoder.yudao.module.call.service.record.CallRecordService;
import cn.iocoder.yudao.module.call.service.task.CallTaskService;
import cn.iocoder.yudao.module.crm.api.clue.CrmClueApi;
import cn.iocoder.yudao.module.crm.api.clue.dto.CrmClueDTO;
import cn.iocoder.yudao.module.crm.api.contact.CrmContactApi;
import cn.iocoder.yudao.module.crm.api.contact.dto.CrmContactDTO;
import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerDTO;
import cn.iocoder.yudao.module.crm.api.encrypt.EncryptMobileApi;
import cn.iocoder.yudao.module.crm.api.encrypt.dto.MobileEncryptConfigDTO;
import cn.iocoder.yudao.module.crm.api.level.CrmLevelConfigApi;
import cn.iocoder.yudao.module.crm.api.level.dto.CrmLevelConfigDTO;
import cn.iocoder.yudao.module.ent.api.company.EntCompanyApi;
import cn.iocoder.yudao.module.ent.document.EntCompany;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;

@Tag(name = "呼叫中心 - 通话录音")
@RestController
@RequestMapping("/call/record")
@Validated
@Slf4j
public class CallRecordController {

    @Resource
    private CallRecordService callRecordService;

    @Resource
    private IvrIntentionLabelStatisticsService ivrIntentionLabelStatisticsService;

    @Resource
    private CallTaskService callTaskService;

    @Resource
    private AdminUserApi adminUserApi;

    @Resource
    private EntCompanyApi entCompanyApi;

    @Resource
    private CrmCustomerApi crmCustomerApi;

    @Resource
    private CrmContactApi crmContactApi;

    @Resource
    private CrmClueApi crmClueApi;

    @Resource
    private EncryptMobileApi encryptMobileApi;

    @Resource
    private CrmLevelConfigApi crmLevelConfigApi;

    @PostMapping("/create")
    @Operation(summary = "创建通话录音")
    @PreAuthorize("@ss.hasPermission('call:record:create')")
    public CommonResult<Long> createRecord(@Valid @RequestBody CallRecordSaveReqVO createReqVO) {
        return success(callRecordService.createRecord(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新通话录音")
    @PreAuthorize("@ss.hasPermission('call:record:update')")
    public CommonResult<Boolean> updateRecord(@Valid @RequestBody CallRecordSaveReqVO updateReqVO) {
        callRecordService.updateRecord(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除通话录音")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('call:record:delete')")
    public CommonResult<Boolean> deleteRecord(@RequestParam("id") Long id) {
        callRecordService.deleteRecord(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得通话录音")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('call:record:query')")
    public CommonResult<CallRecordRespVO> getRecord(@RequestParam("id") Long id) {
        CallRecordDO record = callRecordService.getRecord(id);
        if (Objects.isNull(record)) {
            return success(null);
        }
        CallRecordRespVO result = BeanUtils.toBean(record, CallRecordRespVO.class);

        if (Objects.equals(1, record.getTransStatus())) {
            CallRecordTranslateDO callRecordTranslateDO = callRecordService.getRecordTranslate(id);
            if (Objects.nonNull(callRecordTranslateDO)) {
                result.setContent(callRecordTranslateDO.getContent());
                result.setSummary(callRecordTranslateDO.getSummary());
            }
        }

        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(ListUtil.of(result.getOwnerUserId()));
        buildRespVO(result, userMap);

        MobileEncryptConfigDTO useEncrypt = encryptMobileApi.useEncrypt();
        result.setEncryptCallee(encryptMobileApi.convertEncryptMobile(useEncrypt, result.getCallee()));


        if (record.getCallType().equals(CallTypeEnum.BATCH_IVR_CALL.getValue())) {
            //ivr类型的查对应意向信息
            IvrIntentionLabelStatisticsDO ivrIntentionLabelStatisticsDO = ivrIntentionLabelStatisticsService.getByCallId(record.getReqNo());
            if (ivrIntentionLabelStatisticsDO != null) {
                result.setFlowId(ivrIntentionLabelStatisticsDO.getFlowId());
                result.setCallId(ivrIntentionLabelStatisticsDO.getCallId());
                result.setMingzhongsuoyouwenti(ivrIntentionLabelStatisticsDO.getMingzhongsuoyouwenti());
                result.setMingzhongyewuwenti(ivrIntentionLabelStatisticsDO.getMingzhongyewuwenti());
                result.setKendingcishu(ivrIntentionLabelStatisticsDO.getKendingcishu());
                result.setJujuecishu(ivrIntentionLabelStatisticsDO.getJujuecishu());
                result.setKehujianghuacishu(ivrIntentionLabelStatisticsDO.getKehujianghuacishu());
                result.setTonghuashichang(ivrIntentionLabelStatisticsDO.getTonghuashichang());
                result.setKehutonghuaneirong(ivrIntentionLabelStatisticsDO.getKehutonghuaneirong());
                result.setKehutonghuaneirongKeys(ivrIntentionLabelStatisticsDO.getKehutonghuaneirongKeys());
                result.setZouwanzhuliucheng(ivrIntentionLabelStatisticsDO.getZouwanzhuliucheng() == 1 ? "是" : "否");
                result.setKehuzuihouyijuhua(IvrKeywordsBranchTypeEnum.getNameByType(ivrIntentionLabelStatisticsDO.getKehuzuihouyijuhua()));
                result.setLevel(ivrIntentionLabelStatisticsDO.getLevel());
                CrmLevelConfigDTO crmLevelConfigDTO = crmLevelConfigApi.getLevelConfig(ivrIntentionLabelStatisticsDO.getLevel());
                if (crmLevelConfigDTO != null) {
                    result.setLevelName(crmLevelConfigDTO.getName());
                }

            }
        }
        return success(result);
    }

    @GetMapping("/get-summary")
    @Operation(summary = "获得通话录音")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    public CommonResult<CallRecordRespVO> getRecordSummary(@RequestParam("id") Long id) {
        CallRecordDO record = callRecordService.getRecord(id);
        if (Objects.isNull(record)) {
            return success(null);
        }
        if (!Objects.equals(record.getTransStatus(), 1)) {
            return success(null);
        }
        CallRecordTranslateDO callRecordTranslateDO = callRecordService.getRecordTranslate(id);
        if (Objects.isNull(callRecordTranslateDO)) {
            return success(null);
        }
        CallRecordRespVO result = BeanUtils.toBean(record, CallRecordRespVO.class);
        result.setContent(callRecordTranslateDO.getContent());
        result.setSummary(callRecordTranslateDO.getSummary());
        return success(result);
    }

    @PostMapping("/translate")
    @Operation(summary = "创建通话录音转文字")
    @OperateLog(enable = false)
    @PermitAll
    public CommonResult<Boolean> createRecordTranslate(@Valid @RequestBody CallRecordTransReqVO param) {
        callRecordService.createRecordTranslate(param);
        return success(true);
    }

    @PostMapping("/advance-page")
    @Operation(summary = "高级查询-获得线索分页")
    @PreAuthorize("@ss.hasPermission('call:record:query')")
    public CommonResult<PageResult<CallRecordRespVO>> getClueAdvancePage(@Valid @RequestBody PageParam pageVO) {
        PageResult<CallRecordDO> pageResult = callRecordService.getRecordAdvancePage(pageVO, getLoginUserId());
        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(pageResult.getList().stream().map(CallRecordDO::getOwnerUserId).collect(Collectors.toList()));
        PageResult<CallRecordRespVO> result = BeanUtils.toBean(pageResult, CallRecordRespVO.class);
        MobileEncryptConfigDTO useEncrypt = encryptMobileApi.useEncrypt();
        result.getList().forEach(item -> {
            // 设置负责人name
            buildRespVO(item, userMap);
            // 手机号脱敏
            item.setEncryptCallee(encryptMobileApi.convertEncryptMobile(useEncrypt, item.getCallee()));
        });

        return success(result);
    }

    @GetMapping("/page")
    @Operation(summary = "获得通话录音分页")
    @PreAuthorize("@ss.hasPermission('call:record:query')")
    public CommonResult<PageResult<CallRecordRespVO>> getRecordPage(@Valid CallRecordPageReqVO pageReqVO) {
        PageResult<CallRecordDO> pageResult = callRecordService.getRecordPage(pageReqVO, getLoginUserId());
        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(pageResult.getList().stream().map(CallRecordDO::getOwnerUserId).collect(Collectors.toList()));
        PageResult<CallRecordRespVO> result = BeanUtils.toBean(pageResult, CallRecordRespVO.class);
        MobileEncryptConfigDTO useEncrypt = encryptMobileApi.useEncrypt();
        Map<Long, Map<String, CallTaskDO>> callTaskMap = callTaskService.getMapByTaskIds(pageResult.getList().stream().map(CallRecordDO::getTaskId).collect(Collectors.toList()));
        Map<Long, CallRecordTranslateDO> callRecordTranslateDOMap = callRecordService.getRecordTranslateMap(pageResult.getList().stream().map(CallRecordDO::getId).collect(Collectors.toList()));

        result.getList().forEach(item -> {
            // 设置负责人name
            buildRespVO(item, userMap);
            // 手机号脱敏
            item.setEncryptCallee(encryptMobileApi.convertEncryptMobile(useEncrypt, item.getCallee()));
            item.setCallTypeText(CallTypeEnum.getMsg(item.getCallType()));
            //任务名称
            if (callTaskMap.containsKey(item.getChannelId()) && callTaskMap.get(item.getChannelId()).containsKey(item.getTaskId())) {
                item.setTaskName(callTaskMap.get(item.getChannelId()).get(item.getTaskId()).getName());
            }
            //AI意向分析
            MapUtils.findAndThen(callRecordTranslateDOMap, item.getId(), callRecordTranslate -> {
                //有时返回的AI意向分析结果不是标准json,做一下错误拦截
                if (StrUtil.isNotEmpty(callRecordTranslate.getSummary())) {
                    try {
                        String aiLevel = JSONUtil.parseObj(callRecordTranslate.getSummary()).getStr("客户意向度");
                        item.setSummary(aiLevel);
                    } catch (Exception e) {
                        log.error("通话录音-AI意向分析-解析异常", e);
                    }
                }
            });

        });
        return success(result);
    }


    @GetMapping("/page-by-workbench")
    @Operation(summary = "获得通话录音分页")
    @PreAuthorize("@ss.hasPermission('call:record:query')")
    public CommonResult<PageResult<CallRecordRespVO>> getRecordPageByWorkbench(@Valid CallRecordWorkbenchPageReqVO pageReqVO) {
        PageResult<CallRecordDO> pageResult = callRecordService.getRecordPageByWorkbench(pageReqVO);
        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(pageResult.getList().stream().map(CallRecordDO::getOwnerUserId).collect(Collectors.toList()));
        PageResult<CallRecordRespVO> result = BeanUtils.toBean(pageResult, CallRecordRespVO.class);
        result.getList().forEach(item -> {
            // 设置负责人name
            buildRespVO(item, userMap);
        });

        return success(result);
    }

    public void buildRespVO(CallRecordRespVO item, Map<Long, AdminUserRespDTO> userMap) {
        MapUtils.findAndThen(userMap, item.getOwnerUserId(), user -> item.setOwnerUserName(user.getNickname()));
        // 判断source
        if (Objects.isNull(item.getSource())) {
            item.setSourceName("自动外呼");
        } else if (item.getSource().equals("none")) {
            item.setSourceName("手拨");
        } else {
            if (StrUtil.isNotEmpty(item.getSourceId())) {
                switch (item.getSource()) {
                    case "ent":
                        // 从企业大数据查找entName
                        EntCompany companyByEntId = entCompanyApi.getEntCompanyByEntId(item.getSourceId());
                        if (Objects.nonNull(companyByEntId)) {
                            item.setSourceName(companyByEntId.getCompanyName());
                        }
                        break;
                    case "clue":
                        // 从clue查找
                        CrmClueDTO clueByClueId = crmClueApi.getClueByClueId(Long.parseLong(item.getSourceId()));
                        if (Objects.nonNull(clueByClueId)) {
                            item.setSourceName(clueByClueId.getName());
                        }
                        break;
                    case "customer":
                        // 从customer查找
                        CrmCustomerDTO customerByCustomerId = crmCustomerApi.getCustomerByCustomerId(Long.parseLong(item.getSourceId()));
                        if (Objects.nonNull(customerByCustomerId)) {
                            item.setSourceName(customerByCustomerId.getName());
                        }
                        break;
                    case "contact":
                        CrmContactDTO contactByContactId = crmContactApi.getContactByContactId(Long.parseLong(item.getSourceId()));
                        if (Objects.nonNull(contactByContactId)) {
                            item.setSourceName(contactByContactId.getName());
                        }
                        break;
                }
            }

        }
    }

    @GetMapping("/page-by-ivr")
    @Operation(summary = "获得ivr通话录音分页")
    @PreAuthorize("@ss.hasPermission('call:record:ivr')")
    public CommonResult<PageResult<CallRecordRespVO>> getRecordPageByIvr(@Valid CallRecordIvrPageReqVO pageReqVO) {
        PageResult<CallRecordIvrDTO> pageResult = callRecordService.getRecordPageByIvr(pageReqVO);
        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(pageResult.getList().stream().map(CallRecordIvrDTO::getOwnerUserId).collect(Collectors.toList()));
        Map<Long, CrmLevelConfigDTO> levelMap = crmLevelConfigApi.getLevelConfigMap(pageResult.getList().stream().map(CallRecordIvrDTO::getLevel).collect(Collectors.toList()));
        MobileEncryptConfigDTO useEncrypt = encryptMobileApi.useEncrypt();

        Map<Long, CallRecordTranslateDO> callRecordTranslateDOMap = callRecordService.getRecordTranslateMap(pageResult.getList().stream().map(CallRecordIvrDTO::getId).collect(Collectors.toList()));
        Map<Long, Map<String, CallTaskDO>> callTaskMap = callTaskService.getMapByTaskIds(pageResult.getList().stream().map(CallRecordIvrDTO::getTaskId).collect(Collectors.toList()));

        PageResult<CallRecordRespVO> result = BeanUtils.toBean(pageResult, CallRecordRespVO.class, item -> {
            // 设置负责人name
            buildRespVO(item, userMap);
            // 手机号脱敏
            item.setEncryptCallee(encryptMobileApi.convertEncryptMobile(useEncrypt, item.getCallee()));
            //意向等级
            MapUtils.findAndThen(levelMap, item.getLevel(), levelConfig -> {
                item.setLevelName(levelConfig.getName());
            });
            //AI意向分析
            MapUtils.findAndThen(callRecordTranslateDOMap, item.getId(), callRecordTranslate -> {
                String aiLevel = JSONUtil.parseObj(callRecordTranslate.getSummary()).getStr("客户意向度");
                item.setSummary(aiLevel);
            });

            item.setCallTypeText(CallTypeEnum.getMsg(item.getCallType()));
            //任务名称
            if (callTaskMap.containsKey(item.getChannelId()) && callTaskMap.get(item.getChannelId()).containsKey(item.getTaskId())) {
                item.setTaskName(callTaskMap.get(item.getChannelId()).get(item.getTaskId()).getName());
            }
        });
        return success(result);
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出通话录音 Excel")
    @PreAuthorize("@ss.hasPermission('call:record:export')")
    @OperateLog(type = EXPORT)
    public void exportRecordExcel(@Valid CallRecordPageReqVO pageReqVO,
                                  HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<CallRecordDO> list = callRecordService.getRecordPage(pageReqVO, getLoginUserId()).getList();
        // 导出 Excel
        ExcelUtils.write(response, "通话录音.xls", "数据", CallRecordRespVO.class,
                BeanUtils.toBean(list, CallRecordRespVO.class));
    }

    @PostMapping("/add-remark")
    @Operation(summary = "创建通话录音备注")
    @OperateLog(enable = false)
    @PermitAll
    public CommonResult<Boolean> createRecordRemark(@Valid @RequestBody CallRecordRemarkReqVO reqVO) {
        callRecordService.createRecordRemark(reqVO);
        return success(true);
    }

}